#include "particle_drawer.h"

ParticleDrawer::ParticleDrawer(ParticleShaderProgram *program
                               , ParticleSystem *particleSystem)
    :VertexDrawer(program), m_particleSystem(particleSystem){

    assert(m_vao);
    assert(m_vbo);
    // 初始化纹理
    QImage img = QImage(":/res/particle_texture.png");
    m_texture = new QOpenGLTexture(img);
    m_texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
    m_texture->setMagnificationFilter(QOpenGLTexture::Linear);
    m_texture->release();
    // 设置attribute变量
    ParticleShaderProgram *psProgram = static_cast<ParticleShaderProgram *>(m_program);
    int start = 0;
    psProgram->setAttribute(psProgram->attrPosition()
                            , POSITION_COMPONENT_COUNT
                            , STRIDE
                            , start);
    start += POSITION_COMPONENT_COUNT * sizeof(float) ;
    psProgram->setAttribute(psProgram->attrColor()
                            , COLOR_COMPONENT_COUNT
                            , STRIDE
                            , start);
    start += COLOR_COMPONENT_COUNT * sizeof(float);
    psProgram->setAttribute(psProgram->attrDirection()
                            , DIRECTION_COMPONENT_COUNT
                            , STRIDE
                            , start);
    start += DIRECTION_COMPONENT_COUNT * sizeof(float);
    psProgram->setAttribute(psProgram->attrStartTime()
                            , STARTTIME_COMPONENT_COUNT
                            , STRIDE
                            , start);
    // enable attribute变量
    psProgram->enableAttribute(psProgram->attrPosition());
    psProgram->enableAttribute(psProgram->attrColor());
    psProgram->enableAttribute(psProgram->attrDirection());
    psProgram->enableAttribute(psProgram->attrStartTime());
}

void ParticleDrawer::draw() {
    if (m_particleSystem->currentParticleCount() < 1)
        return;
    m_program->bind();
    m_vao->bind();
    // 顶点数据搬运至显存
    m_vbo->allocate(m_particleSystem->vertexData()
                    , m_particleSystem->vertexDataByteSize());
    // 变换矩阵
    glUniformMatrix4fv(m_program->uniformMatrix(), 1, false, m_matrix.data());
    // 设置当前时间
    ParticleShaderProgram *psProgram = static_cast<ParticleShaderProgram *>(m_program);
    glUniform1f(psProgram->uniformCurrentTime(), m_currentTime);
    // 设置纹理
    m_texture->bind();
    psProgram->program()->setUniformValue(psProgram->uniformTextureUnit(), 0);

    glDrawArrays(GL_POINTS, 0, m_particleSystem->currentParticleCount());
}
